Các thuật toán Sắp_xếp_tô_pô

Các thuật toán sắp xếp tô pô thường có thời gian tuyến tính trong số nút cộng với số cung ( O ( | V | + | E | ) {\displaystyle O(|V|+|E|)} ).

Một trong những thuật toán này, phát hiện bởi Kahn năm 1962[1], hoạt động bằng cách lần lượt chọn các đỉnh theo thứ tự đúng như thứ tự tô pô. Đầu tiên, xác định một danh sách các "nút bắt đầu" không có cung vào và chèn chúng vào một tập S. Trong một đồ thị có hướng không có chu trình, luôn có ít nhất một nút như vậy. Sau đó:

L ← danh sách rỗng (cuối cùng sẽ chứa danh sách đã sắp xếp)S ← tập hợp các nút không có cung vàowhile S khác rỗng do    loại bỏ một nút n từ S    chèn n vào L    for each nút m sao cho có cung e từ n đến m do        loại bỏ cung e từ đồ thị        if m không có cung vào then            chèn m vào Sif đồ thị vẫn còn cung then    thông báo lỗi (đồ thị có ít nhất một chu trình)else     thông báo thứ tự tô pô là L

Nếu đồ thị là một DAG, danh sách L luôn chứa một thứ tự hợp lệ(thứ tự tô pô không nhất thiết là duy nhất). Nếu đồ thị không là DAG thì nó có ít nhất một chu trình và do đó không thể có thứ tự tô pô.

Lưu ý rằng S có thể lựa chọn phần tử n một cách tùy ý. Tùy thuộc vào thứ tự các nút n được loại bỏ từ S, một thứ tự tô pô khác nhau được tạo ra. Một biến thể của thuật toán của Kahn sử dụng thứ tự từ điển cho việc lựa chọn n là một thành phần quan trọng của thuật toán Coffman-Graham cho lập kế hoạch song song và vẽ đồ thị lớp.

Có một thuật toán khác cho sắp xếp tô pô dựa trên tìm kiếm theo chiều sâu. Đối với thuật toán này, các cung chỉ theo hướng ngược lại so với thuật toán trước: có một cung từ x đến y nếu công việc x phụ thuộc vào công việc y (nói cách khác, nếu công việc y phải hoàn thành trước khi công việc x có thể bắt đầu). Thuật toán duyệt qua các nút của đồ thị, trong một trật tự tùy ý, và thực hiện tìm kiếm theo chiều sâu cho đến khi tìm đến một nút đã được thăm:

L ← danh sách rỗng (cuối cùng sẽ chứa thứ tự sắp xếp)S ← tập hợp các nút không có cung vàofor each nút n trong S do    thăm(n) function thăm(nút ​​n)    if chưa thăm n then        đánh dấu n là đã thăm        for each nút m sao cho có cung từ n đến m do            thăm(m)        chèn n vào L

Lưu ý rằng mỗi nút n được thêm vào danh sách L chỉ sau khi đã thăm tất cả các nút khác mà n phụ thuộc vào(tất cả các nút hậu duệ của n trong đồ thị). Cụ thể là, khi thuật toán thêm nút n, nó đảm bảo rằng tất cả các nút n phụ thuộc vào đã có trong danh sách L: chúng đã được thêm vào L hoặc do lời gọi đệ quy đến thăm(), hoặc do một lời gọi đến thăm() từ trước. Vì mỗi cung và mỗi nút được thăm một lần, thuật toán chạy trong thời gian tuyến tính. Lưu ý rằng mã giả trên không thể phát hiện trường hợp lỗi khi đồ thị có chu trình. Thuật toán có thể được thay đổi để phát hiện chu trình bằng cách kiểm tra có nút nào được thăm nhiều hơn một lần trong bất kỳ một chuỗi lồng nhau của các lời gọi đệ quy đến thăm(). Thuật toán này có thể đã được mô tả lần đầu tiên bởi Tarjan năm 1976[2].